#include "stdafx.h"
#include "RawData.h"
#include "CoreException.h"
#include "System.h"
#include <cstring>
#ifndef WIN32
#include <netinet/in.h>
#endif

namespace Core
{

	RawData::RawData()
	{
		m_Size = DATASIZE;
		Reset();
	}

	RawData::~RawData()
	{
	}

	unsigned short RawData::GetSize() const
	{
		return m_Size;
	}

	unsigned short RawData::GetLength() const
	{
		return m_WriteIterator;
	}

	unsigned short RawData::GetRemaining() const
	{
	    if (m_WriteIterator <= m_ReadIterator)
            return 0;
        else
            return (m_WriteIterator-m_ReadIterator);
	}

	bool RawData::IsFull() const
	{
		return (m_Size==m_WriteIterator);
	}

	void RawData::Reset()
	{
		memset(m_Data, 0, m_Size);
		ResetReadIterator();
		ResetWriteIterator();
	}

	void RawData::ResetWriteIterator()
	{
		m_WriteIterator=0;
	}

	void RawData::ResetReadIterator()
	{
		m_ReadIterator=0;
	}

	unsigned char RawData::PeekChar()
	{
		if(m_ReadIterator+1>m_Size)
		{
			throw RawDataException();
		}
		char t_Char = m_Data[m_ReadIterator];
		return t_Char;
	}

	unsigned char RawData::ReadChar()
	{
		if(m_ReadIterator+1>m_WriteIterator)
		{
			throw RawDataException();
		}
		char t_Char = m_Data[m_ReadIterator];
		m_ReadIterator += 1;
		return t_Char;
	}

	void RawData::WriteChar(unsigned char p_Data)
	{
		if(m_WriteIterator+1>m_Size)
		{
			throw RawDataException();
		}
		m_Data[m_WriteIterator] = p_Data;
		m_WriteIterator += 1;
	}

	unsigned short RawData::ReadShort()
	{
		if(m_ReadIterator+2>m_WriteIterator)
		{
			throw RawDataException();
		}
		short t_Short;
		memcpy(&t_Short, &m_Data[m_ReadIterator], 2);
		m_ReadIterator += 2;
		return ntohs(t_Short);
	}

	void RawData::WriteShort(unsigned short p_Data)
	{
		if(m_WriteIterator+2>m_Size)
		{
			throw RawDataException();
		}
		short t_Short = htons(p_Data);
		memcpy(&m_Data[m_WriteIterator], &t_Short, 2);
		m_WriteIterator += 2;
	}

	unsigned long RawData::Read24Bit()
	{
		if(m_ReadIterator+3>m_WriteIterator)
		{
			throw RawDataException();
		}
		long t_Long = 0;
		t_Long |= m_Data[m_WriteIterator+0] << 16;
		t_Long |= m_Data[m_WriteIterator+1] << 8;
		t_Long |= m_Data[m_WriteIterator+2] << 0;
		m_WriteIterator += 3;
		return t_Long;
	}

	void RawData::Write24Bit(unsigned long p_24Bit)
	{
		if(m_WriteIterator+3>m_Size)
		{
			throw RawDataException();
		}
		m_Data[m_WriteIterator+0] = (unsigned char) (p_24Bit >> 16) & 0xFF;
		m_Data[m_WriteIterator+1] = (unsigned char) (p_24Bit >> 8) & 0xFF;
		m_Data[m_WriteIterator+2] = (unsigned char) (p_24Bit >> 0) & 0xFF;
		m_WriteIterator += 3;
	}

	unsigned long RawData::ReadLong()
	{
		if(m_ReadIterator+4>m_WriteIterator)
		{
			throw RawDataException();
		}
		long t_Long;
		memcpy(&t_Long, &m_Data[m_ReadIterator], 4);
		m_ReadIterator += 4;
		return ntohl(t_Long);
	}

	void RawData::WriteLong(unsigned long p_Data)
	{
		if(m_WriteIterator+4>m_Size)
		{
			throw RawDataException();
		}
		long t_Long = htonl(p_Data);
		memcpy(&m_Data[m_WriteIterator], &t_Long, 4);
		m_WriteIterator += 4;
	}

	unsigned short RawData::ReadFromMemory(unsigned char*& p_Data, unsigned short p_Length)
	{
		unsigned short t_Length = p_Length;
		if(t_Length>(m_Size-(m_WriteIterator)))
		{
			throw RawDataException();
		}
		for(unsigned short i=0; i<t_Length; i++)
		{
			m_Data[m_WriteIterator+i] = p_Data[i];
		}
		m_WriteIterator += t_Length;
		return t_Length;
	}

	unsigned short RawData::WriteToMemory(unsigned char*& p_Data, unsigned short p_Length)
	{
		unsigned short t_Length = p_Length;
		if(t_Length>(m_WriteIterator-(m_ReadIterator)))
		{
			throw RawDataException();
		}
		for(unsigned short i=0; i<t_Length; i++)
		{
			p_Data[i] = m_Data[m_ReadIterator+i];
		}
		m_ReadIterator += t_Length;
		return t_Length;
	}

	void RawData::ReadFromIStream(std::istream& p_IStream, unsigned short p_Length)
	{
		if(p_IStream.eof()) throw FileException();
		if(p_Length>DATASIZE)
		{
			throw RawDataException();
		}
		unsigned char t_Data[DATASIZE];
		unsigned char* t_PData = t_Data;
		p_IStream.read((char*)t_Data, p_Length);
		ReadFromMemory(t_PData, p_Length);
		if(p_IStream.eof()) throw FileException();
	}

	void RawData::WriteToOStream(std::ostream& p_OStream, unsigned short p_Length)
	{
		if(p_Length>DATASIZE)
		{
			throw RawDataException();
		}
		unsigned char t_Data[DATASIZE];
		unsigned char* t_PData = t_Data;
		WriteToMemory(t_PData, p_Length);
		p_OStream.write((char*)t_Data, p_Length);
	}

	unsigned char& RawData::operator[](unsigned short p_Index)
	{
		return m_Data[p_Index];
	}

	unsigned short RawData::GetReadIterator() const
	{
		return m_ReadIterator;
	}

	unsigned short RawData::GetWriteIterator() const
	{
		return m_WriteIterator;
	}

	void RawData::SetReadIterator(unsigned short p_Index)
	{
	    if (p_Index > m_WriteIterator)
            m_WriteIterator = m_ReadIterator;
        else
            m_ReadIterator = p_Index;
	}

	void RawData::SetWriteIterator(unsigned short p_Index)
	{
		m_WriteIterator = p_Index;
	}

	void RawData::FromString(std::string p_String)
	{
		Reset();
		unsigned int t_Length = (unsigned int) p_String.length();
		if(GetSize()<t_Length)
		{
			t_Length = GetSize();
		}
		for(unsigned int i=0; i<t_Length; i++)
		{
			m_Data[i] = p_String[i];
		}
		m_WriteIterator = t_Length;
	}


	std::string RawData::ToString() const
	{
		std::string t_String = "";
		for(int i=0; i<GetLength(); i++)
		{
			t_String += m_Data[i];
		}
		return t_String;
	}

	std::string RawData::ToHexString()
	{
		std::ostringstream t_SStream;
		for(int i=0; i<GetLength(); i++)
		{
			std::string t_String = System::ToRadixString(m_Data[i], 16);
			if(t_String.size()==1) t_String = "0" + t_String;
			t_SStream << t_String << " ";
		}
		return t_SStream.str();
	}
}
